#include <os/driver.h>
#include <os/initcall.h>
#include <os/debug.h>
#include <driver/zero.h>
#include <sys/res.h>
#include <lib/list.h>

static iostatus_t ZeroEntry(driver_object_t *driver)
{
    iostatus_t status = IO_SUCCESS;
    device_object_t *devobj;

    status = IoCreateDevice(driver, 0, DEVICE_NAME, DEVICE_TYPE_VIRTUAL_CHAR, &devobj);
    if (status != IO_SUCCESS)
    {
        KPrint(PRINT_ERR "zero device object create failed!\n");
        return status;
    }
    devobj->flags = IOREQ_BUFFER_IO;
    return status;
}

static iostatus_t ZeroExit(driver_object_t *driver)
{
    device_object_t *devobj, *next;
    iostatus_t status;

    list_traversal_all_owner_to_next_safe(devobj, next, &driver->device_list, list)
    {
        IoDeleteDevice(devobj);
    }

    string_del(&driver->name);
    return IO_SUCCESS;
}

static iostatus_t ZeroOpen(device_object_t *devobj, io_request_t *ioreq)
{
    iostatus_t status = IO_SUCCESS;


    ioreq->io_status.status = IO_SUCCESS;
    ioreq->io_status.info = 0;
    IoCompleteRequest(ioreq);

    return status;
}

static iostatus_t ZeroClose(device_object_t *devobj, io_request_t *ioreq)
{
    iostatus_t status = IO_SUCCESS;

    ioreq->io_status.status = IO_SUCCESS;
    ioreq->io_status.info = 0;
    IoCompleteRequest(ioreq);

    return status;
}

static iostatus_t ZeroRead(device_object_t *device, io_request_t *ioreq)
{
    iostatus_t status = IO_SUCCESS;


    int len = ioreq->parame.read.len;
    uint8_t *data = ioreq->user_buff;
    int _total=0;

    while (len-- > 0)
    {
        *data++ = 0;
        _total++;
    }
    ioreq->io_status.status = IO_SUCCESS;
    ioreq->io_status.info = _total;
    IoCompleteRequest(ioreq);
    return status;
}

iostatus_t ZeroDriverFunc(driver_object_t *driver)
{
    iostatus_t status = IO_SUCCESS;

    driver->driver_enter = ZeroEntry;
    driver->driver_exit = ZeroExit;
    // dispatch function
    driver->dispatch_fun[IOREQ_OPEN] = ZeroOpen;
    driver->dispatch_fun[IOREQ_CLOSE] = ZeroClose;
    driver->dispatch_fun[IOREQ_READ] = ZeroRead;
    // driver name
    string_new(&driver->name, DRIVER_NAME, DRIVER_NAME_LEN);

    return status;
}

static __init void ZeroDriverEntry()
{
    if (DriverObjectCreate(ZeroDriverFunc) < 0)
        KPrint(PRINT_ERR "[driver] %s driver create failed!\n", DRIVER_NAME);
}

driver_initcall(ZeroDriverEntry);